/**
 * @class   wosh::gui::WidgetUriSelector
 * @brief   
 *          
 *          
 *
 ****************************************************************************
 * @version $Id: WidgetUriSelector.h 2191 2010-03-22 23:07:12Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Gui_WidgetUriSelector_H__
 #define __WOSH_Gui_WidgetUriSelector_H__

 #include <core/URI.h>
 #include <framework/gui/IWidget.h>
 #include <framework/gui/WoshTableModel.h>

 #include "ui_WidgetUriSelector.h"
 #include <QtGui/QCompleter>

 #include <QtGui/QTreeView>

 #include <QDirModel>


namespace Ui {
    class WidgetUriSelector;
}

namespace wosh {
 namespace gui {

typedef wosh::TreeNode22<std::string> NodeUriStr;


class URITreeModel :  public QAbstractItemModel  {

	Q_OBJECT

	public:
		URITreeModel(NodeUriStr* item_root, QObject *parent = 0)
			: QAbstractItemModel(parent) {
			this->rootnode = item_root;
		 }

		virtual ~URITreeModel() { }

	public:
		int rowCount(const QModelIndex &parent = QModelIndex()) const {
			NodeUriStr* parentItem = NULL;
			if (!parent.isValid())
				parentItem = this->rootnode;
			else
				parentItem = static_cast<NodeUriStr*>(parent.internalPointer());
			if (parentItem == NULL)
				return 0;
			return parentItem->getChildren().size();
		 }

		int columnCount(const QModelIndex &parent = QModelIndex()) const {
			(void)parent;
			//if ( this->items == NULL ) return 0;
			return 1;
		 }

	    virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const {
			if (!hasIndex(row, column, parent)) return QModelIndex();
			NodeUriStr* parentItem = NULL;
			if (!parent.isValid())
				parentItem = this->rootnode;
			else
				parentItem = static_cast<NodeUriStr*>(parent.internalPointer());
			if ( parentItem == NULL )
				return QModelIndex();

			NodeUriStr* childItem = parentItem->getChildren().itemAt(row);
			if (childItem)
				return createIndex(row, column, childItem);
			else
				return QModelIndex();
		 }

	    virtual QModelIndex parent(const QModelIndex &child) const {
			 if ( !child.isValid() ) return QModelIndex();
		    NodeUriStr* childItem = static_cast<NodeUriStr*>(child.internalPointer());
			if ( childItem == NULL )
				return QModelIndex();

			NodeUriStr* parentItem = childItem->getParent();
			if ( parentItem == this->rootnode )
				return QModelIndex();
			if ( parentItem == NULL )
				return QModelIndex();
			NodeUriStr* parentParentItem = parentItem->getParent();
			if ( parentParentItem == NULL )
				return createIndex(1,0, parentItem);
			int childIndex = parentParentItem->getChildren().indexOf(parentItem);
			if( childIndex < 0 ) childIndex = 0;
			return createIndex(childIndex,0, parentItem);
		 }

		QVariant data(const QModelIndex &index, int role) const {
			if ( !index.isValid() )	return QVariant();
			NodeUriStr* item = static_cast<NodeUriStr*>(index.internalPointer());
			if ( item == NULL )
				return QVariant();

			if ( role == Qt::DisplayRole || role == Qt::ToolTipRole ) {
				return QVariant( item->getContent().c_str() );
			 }
			else if ( role == Qt::EditRole ) { // cos completer!
				return QVariant( item->getContent().c_str() );
				/* switch (index.column()) {
					case 0: {
						string outstr = "";
						item->get_full_path(outstr);
						return QVariant(outstr.c_str());
					}
					default:
						return QVariant( item->getContent().c_str() );
				 } */
			 }
			return QVariant();
		 }

		QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
		 {
			if (role != Qt::DisplayRole)
				return QVariant();

			if (orientation == Qt::Horizontal) {
				 switch(section) {
					case 0:		return QString("Name");
				  }
				 return QString("Col%1").arg(section);
			 }
			return QVariant();
		 }


		Qt::ItemFlags flags(const QModelIndex &index) const {
			if (!index.isValid())
				return 0;
			return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
		 }

	protected:
		NodeUriStr* rootnode;

}; // class def



class URITreeModelCompleter : public QCompleter  {

    Q_OBJECT

	public:
		URITreeModelCompleter(QObject *parent = 0) : QCompleter(parent) { }
		URITreeModelCompleter(QAbstractItemModel *model, QObject *parent = 0) : QCompleter(model, parent) { }

		virtual ~URITreeModelCompleter() { }

	protected:

		virtual QStringList splitPath(const QString &path) const
		{
			URI uri( path.toLatin1().data() );
			QStringList res;
			if (path.isEmpty())
				return res;
			res << uri.getKernelName().c_str();
			for(unsigned int i=0; i<uri.getPath().size(); i++)
				res << uri.getPath().at(i).c_str();
			if ( !uri.getName().empty() )
				res << QString(uri.getName().c_str());

			return res;
		}

		virtual QString pathFromIndex(const QModelIndex &index) const
		 {
			NodeUriStr* item = static_cast<NodeUriStr*>(index.internalPointer());
			if ( item == NULL )
				return QCompleter::pathFromIndex(index);
			URI temp = URICollector::resolve(item);
			return QString(temp.toString().c_str());
		 }

}; // class def





class WidgetUriSelector :  public QWidget  {

	Q_OBJECT

	public:

		WidgetUriSelector(QWidget *parent = 0) : QWidget(parent)
		 {
			this->m_ui = new Ui::WidgetUriSelector();
			this->m_ui->setupUi(this);

			this->tvBrowser = NULL;
			this->model = new URITreeModel(reinterpret_cast<NodeUriStr*>(URICollector::getTree().getRoot()), this);

			this->completer = new URITreeModelCompleter(this);
			this->completer->setModel(this->model);
			this->completer->setCompletionMode(QCompleter::PopupCompletion);
			int cs = 0;
			this->completer->setCaseSensitivity(cs ? Qt::CaseSensitive : Qt::CaseInsensitive);
			this->completer->setWrapAround(true);

			this->m_ui->lineEdit->setCompleter(this->completer);

			QObject::connect(this->m_ui->tBtnTool, SIGNAL(clicked()), this, SLOT(btnClicked()));

			QObject::connect(this->completer, SIGNAL(activated(const QString&)), this, SLOT(completer_activated(const QString&)));
			QObject::connect(this->m_ui->lineEdit, SIGNAL(editingFinished()), this, SLOT(editor_editingFinished()));

			loadLocalURI();
		 }

		virtual ~WidgetUriSelector() {
			if ( this->tvBrowser != NULL )
				delete this->tvBrowser; this->tvBrowser = NULL;
		 }

	public:

		virtual void loadLocalURI()
		 {

		 }

	public:

		void showLabel( bool visible ) {
			this->m_ui->lblURI->setVisible(visible);
		 }

		const URI& getTargetURI() const			{ return this->targetURI; }
		URI& getTargetURI()						{ return this->targetURI; }

		void setTargetURI( const URI& uri )
		 {
			this->targetURI = uri;
			this->m_ui->lineEdit->setText( uri.toString().c_str() );
 		}

	protected:

		void changeEvent(QEvent *e)
		 {
			QWidget::changeEvent(e);
			switch (e->type()) {
				case QEvent::LanguageChange:
				m_ui->retranslateUi(this);
				break;
			default: break;
			}
		 }

		void updateURI()
		 {
			this->targetURI.fromString(this->m_ui->lineEdit->text().toLatin1().data());
		 }

	public slots:

		virtual void refreshAll() {
		 }

		virtual void showBrowser()
		 {
			if ( this->tvBrowser == NULL ) {
				this->tvBrowser = new QTreeView();
				this->tvBrowser->setWindowTitle( tr("URI Browser") );
				QObject::connect(this->tvBrowser, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(browser_doubleClicked(const QModelIndex&)));
			 }
			this->tvBrowser->setModel(this->model);
			this->tvBrowser->move( this->cursor().pos() );
			this->tvBrowser->show();
		 }

	protected slots:

		void browser_doubleClicked( const QModelIndex& index )
		 {
		    NodeUriStr* item = static_cast<NodeUriStr*>(index.internalPointer());
			if ( item == NULL )
				return;
			URI temp = URICollector::resolve(item);
			this->m_ui->lineEdit->setText( temp.toString().c_str() );
			updateURI();
			emit changedURI( this->targetURI );
			this->tvBrowser->hide();
		 }

		void editor_editingFinished()
		 {
			updateURI();
			emit changedURI( this->targetURI );
		 }

		void btnClicked() { showBrowser(); }
		 
		void completer_activated( const QString & text )
		 {
			this->targetURI.fromString(text.toLatin1().data());
			emit changedURI( this->targetURI );
		 }

	signals:

		void changedURI( const URI& uri );


	protected:
		URITreeModel* model;
		URITreeModelCompleter* completer;


		QTreeView* tvBrowser;

		URI targetURI;

	private:
		Ui::WidgetUriSelector *m_ui;


}; // class def

 }; // namespace gui
}; // namespace wosh


#endif //__WOSH_Gui_WidgetUriSelector_H__
